<template>
  <div>
    <canvas ref="canvasRef" :width="canvasWidth" :height="canvasHeight" style="border:1px solid #ccc" />

    <div style="margin-top:10px;">
      <input type="file" @change="loadImage" multiple />

      <label style="margin-left:10px;">
        分辨率宽：
        <input type="number" v-model.number="canvasWidth" min="100" max="2000"/>
      </label>
      <label style="margin-left:10px;">
        分辨率高：
        <input type="number" v-model.number="canvasHeight" min="100" max="2000"/>
      </label>

      <label style="margin-left:10px;">
        字体颜色：
        <input type="color" v-model="fontColor" />
      </label>

      <label style="margin-left:10px;">
        字体大小：
        <input type="number" v-model.number="fontSize" min="8" max="100" />
      </label>

      <label style="margin-left:10px;">
        文字内容：
        <input type="text" v-model="textContent" placeholder="请输入文字" />
      </label>

      <button @click="addText" style="margin-left:10px;">添加文字</button>
      <button @click="bringTextToFront" style="margin-left:10px;">文字置顶</button>
      <button @click="undo" style="margin-left:10px;">撤销</button>
      <button @click="deleteActiveObject" style="margin-left:10px;">删除选中对象</button>
      <button @click="exportImage" style="margin-left:10px;">保存图片</button>

    </div>
  </div>
</template>

<script setup>
import {onMounted, ref, watch} from 'vue';
import {fabric} from 'fabric';

const canvasRef = ref(null);
const canvas = ref(null);

const canvasWidth = ref(1444);
const canvasHeight = ref(1444);

const fontColor = ref('#ff0000');
const fontSize = ref(24);
const textContent = ref('商品描述');

const historyStack = [];
let historyIndex = -1;

onMounted(() => {
  canvas.value = new fabric.Canvas(canvasRef.value, {
    preserveObjectStacking: true
  });
  pushHistory();
});

watch([canvasWidth, canvasHeight], ([w, h]) => {
  if (!canvas.value) return;

  canvas.value.setWidth(w);
  canvas.value.setHeight(h);
  canvas.value.renderAll();

  canvas.value.getObjects('image').forEach(img => {
    scaleImageToCanvas(img, w, h);
  });
  canvas.value.renderAll();
});

function pushHistory() {
  if (!canvas.value) return;
  const json = canvas.value.toJSON();
  historyStack.splice(historyIndex + 1);
  historyStack.push(json);
  historyIndex++;
}

function undo() {
  if (historyIndex <= 0) return;
  historyIndex--;
  canvas.value.loadFromJSON(historyStack[historyIndex], () => {
    canvas.value.renderAll();
  });
}

function loadImage(e) {
  const files = e.target.files;
  if (!files.length) return;

  Array.from(files).forEach(file => {
    const reader = new FileReader();
    reader.onload = () => {
      fabric.Image.fromURL(reader.result, (img) => {
        scaleImageToCanvas(img, canvasWidth.value, canvasHeight.value);

        img.set({
          left: img.left,
          top: img.top,
          selectable: true,
          evented: true,
          hasControls: true,
          hasBorders: true,
          opacity: 1
        });

        canvas.value.add(img);
        img.moveTo(canvas.value.getObjects().length - 1);
        canvas.value.renderAll();
        pushHistory();
      });
    };
    reader.readAsDataURL(file);
  });

  e.target.value = '';
}

function scaleImageToCanvas(img, canvasW, canvasH) {
  const scaleX = canvasW / img.width;
  const scaleY = canvasH / img.height;
  const scale = Math.max(scaleX, scaleY);
  img.scale(scale);

  img.set({
    left: (canvasW - img.width * scale) / 2,
    top: (canvasH - img.height * scale) / 2
  });
}

function addText() {
  if (!canvas.value) return;
  const text = new fabric.Text(textContent.value || ' ', {
    left: 100,
    top: 100,
    fill: fontColor.value,
    fontSize: fontSize.value,
    fontWeight: 'bold',
    editable: true
  });
  canvas.value.add(text);
  text.bringToFront();
  canvas.value.setActiveObject(text);
  canvas.value.renderAll();
  pushHistory();
}

function bringTextToFront() {
  const active = canvas.value.getActiveObject();
  if (active && active.type === 'textbox') {
    active.bringToFront();
    canvas.value.renderAll();
    pushHistory();
  }
}

function exportImage() {
  if (!canvas.value) return;
  const data = canvas.value.toDataURL({ format: 'png', quality: 1 });
  const link = document.createElement('a');
  link.href = data;
  link.download = 'edited-image.png';
  link.click();
}

function deleteActiveObject() {
  const active = canvas.value.getActiveObject();
  if (active) {
    canvas.value.remove(active);
    canvas.value.discardActiveObject();
    canvas.value.renderAll();
    pushHistory();
  }
}


</script>
